package net.babelphish.altitudesig.SigElements;


import java.lang.reflect.Type;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import com.google.gson.*;


class SigStyleElementDeserializer implements JsonDeserializer<SigElement> {
		
	SigStyleElementDeserializer() {		
	}
	
	@Override
	public SigElement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException {
		SigElementJSONFactory deserializeFactory = new SigElementJSONFactory();
		
		JsonObject elementAttributes = json.getAsJsonObject();
		String deserializeType = elementAttributes.getAsJsonPrimitive("type").getAsString();
		SigElement elementToReturn;
		
		if (deserializeType.equals("composite")) {
			elementToReturn = new CompositeSigElement();
			JsonArray subElements = elementAttributes.getAsJsonArray("_subelements");
			
			for(JsonElement subElement : subElements) {
				SigElement deserializedSubElement = deserializeFactory.getSigStyleElement(subElement.toString()); 
				((CompositeSigElement)elementToReturn).addElement(deserializedSubElement); 
			}
		}
		else
		{
			elementToReturn = deserializeFactory.getSigStyleElement(json.toString(), deserializeType);  
		}
		return elementToReturn;
  }	
}

public class SigElementJSONFactory extends SigElementFactory {

	HashMap<String, Class<? extends SigElement>> _deserializableClasses =
        new HashMap<String, Class<? extends SigElement>>();
	
	private Gson _gson;
	
	public SigElementJSONFactory() {
		this.Register("ratingsChart", RatingChartSigElement.class);
		this.Register("composite", CompositeSigElement.class);
		this.Register("conditional", ConditionalSigElement.class);
		this.Register("conditional", ConditionalSigElement.class);
		
		GsonBuilder builder = new GsonBuilder();		
		builder.registerTypeAdapter(SigElement.class, new SigStyleElementDeserializer());
		_gson = builder.create();
	}
	
	@Override
	public SigElement getSigStyleElement(String styleDefinition) {
		return getSigStyleElement(styleDefinition, null);
	}
	
	public SigElement getSigStyleElement(String styleDefinition, String elementClass) {
		
		try {
			Class<? extends SigElement>  knownClass;
			
			if (elementClass == null) {
				knownClass = SigElement.class;
			}
			else
			{
				knownClass = _deserializableClasses.get(elementClass);
			}
		
			SigElement parsedData = _gson.fromJson(styleDefinition, knownClass);
			return parsedData;
		} 
		catch (Exception e) {
			return new ErrorSigElement();
		}
	}
	
	protected <T extends SigElement> void Register(String typeName, Class<T> classOfT)
	{
		_deserializableClasses.put(typeName, classOfT);
	}

}
